﻿using System;
using System.Workflow.Activities;
using Argos.Data.Model;
using System.Collections.Generic;

namespace Argos.WorkflowServices
{
	/// <summary>
	/// Defines the service interface for a service that is used to run
	/// tests with.
	/// </summary>
	[ExternalDataExchange]
	public interface ITestExecutionService
	{

		/// <summary>
		/// Fired when a test for a target is starting.
		/// </summary>
		event EventHandler<TargetTestedEventArgs> TargetTested;

		/// <summary>
		/// Fired when a test for a target has completed, either successfully or unsuccessfully.
		/// </summary>
		event EventHandler<TargetTestingEventArgs> TargetTesting;



		/// <summary>
		/// When implemented in a class, runs the test for the given target.
		/// </summary>
		/// <param name="targetId">The id of the target whose test to run.</param>
		/// <returns>
		/// The method instance returns the state of the executed test. The state
		/// is defines as a property on a test activity. A test activity must implement
		/// the <see cref="Argos.Activities.Tests.ITestActivity"/> interface.
		/// </returns>
		/// <remarks>
		/// The method must not return until the test is completed or it has timed out.
		/// </remarks>
		object RunTest(Guid targetId);

		/// <summary>
		/// When implemented in a class, runs the given test.
		/// </summary>
		/// <param name="test">The test to run.</param>
		/// <returns>
		/// The method instance returns the state of the executed test. The state
		/// is defines as a property on a test activity. A test activity must implement
		/// the <see cref="Argos.Activities.Tests.ITestActivity"/> interface.
		/// </returns>
		/// <remarks>
		/// The method must not return until the test is completed or it has timed out.
		/// </remarks>
		object RunTest(Test test);

		/// <summary>
		/// When implemented in a class, runs the test in the given list.
		/// </summary>
		/// <param name="tests">The tests to run.</param>
		/// <returns>
		/// The method instance returns the state of all tests executed by the method. The state
		/// is defines as a property on a test activity. A test activity must implement
		/// the <see cref="Argos.Activities.Tests.ITestActivity"/> interface.
		/// </returns>
		/// <remarks>
		/// The method must not return until the test is completed or it has timed out. The
		/// tests in the list must be executed in parallel.
		/// </remarks>
		object RunTests(IList<Test> tests);

	}

	/// <summary>
	/// The event arguments class for the <see cref="TestExecutionServiceBase.TargetTesting"/> event.
	/// </summary>
	public sealed class TargetTestingEventArgs : EventArgs
	{
		public TargetTestingEventArgs(Guid targetId)
		{
			this.TargetId = targetId;
		}

		public Guid TargetId { get; private set; }
	}

	/// <summary>
	/// The event arguments class for the <see cref="TestExecutionServiceBase.TargetTested"/> event.
	/// </summary>
	public sealed class TargetTestedEventArgs : EventArgs
	{
		public TargetTestedEventArgs(Guid targetId, object testState)
		{
			this.TargetId = targetId;
			this.TestState = testState;
		}

		public TargetTestedEventArgs(Guid targetId, Exception exception)
		{
			this.TargetId = targetId;
			this.Exception = exception;
		}

		public Exception Exception { get; private set; }
		public Guid TargetId { get; private set; }
		public object TestState { get; private set; }

	}
}
